package com.springmvc.web.servlet.mvc.method.annotation;

import com.springmvc.web.constant.Const;
import com.springmvc.web.servlet.mvc.method.RequestMappingInfo;
import jakarta.servlet.http.HttpServletRequest;
import com.springmvc.web.context.WebApplicationContext;
import com.springmvc.web.method.HandlerMethod;
import com.springmvc.web.servlet.HandlerExecutionChain;
import com.springmvc.web.servlet.HandlerInterceptor;
import com.springmvc.web.servlet.HandlerMapping;

import java.util.List;
import java.util.Map;


/**
 *  RequestMappingHandlerMapping 实现 HandlerMapping 接口
 *  Description:   专门为 @RequestMapping 注解提供映射的处理器映射器
 */
public class RequestMappingHandlerMapping implements HandlerMapping {

    /**
     * 处理器映射器
     * key 是请求信息
     * value 是请求对应的处理器方法
     */
    private Map<RequestMappingInfo, HandlerMethod> map;

    /**
     * 在创建是给map 赋值
     * @param map
     */
    public RequestMappingHandlerMapping(Map<RequestMappingInfo, HandlerMethod> map) {
        this.map = map;
    }

    @Override
    public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // handlerExecutionChain  处理器执行链  就是HandlerMethod+拦截器
        HandlerExecutionChain handlerExecutionChain = new HandlerExecutionChain();
        // 设置HandlerMethod
        // 从请求中拿到 路径 方式  封装成requestMappingInfo对象
        // 根据requestMappingInfo对象 从map中获取对应的handlerMethod
        // 设置handlerMethod
        String requestURI = request.getServletPath();
        String method = request.getMethod();
        RequestMappingInfo requestMappingInfo = new RequestMappingInfo(requestURI, method);
        HandlerMethod handlerMethod = map.get(requestMappingInfo);
        handlerExecutionChain.setHandler(handlerMethod);
        // 设置拦截器
        WebApplicationContext webApplicationContext = (WebApplicationContext) request.getServletContext().getAttribute(Const.WEB_APPLICATION_CONTEXT);
        List<HandlerInterceptor> interceptors = (List<HandlerInterceptor>) webApplicationContext.getBean(Const.INTERCEPTORS);
        handlerExecutionChain.setInterceptors(interceptors);
        return handlerExecutionChain;
    }
}
